from typing import Dict, List, Optional, Any, Union

from langchain.tools import BaseTool
from sqlalchemy.orm import Session

# 尝试导入所有工具管理器，允许某些导入失败
try:
    from tools.service.getCurrentTime import current_time_tool_manager

    _CURRENT_TIME_AVAILABLE = True
except ImportError as e:
    print(f"⚠️ getCurrentTime工具导入失败: {e}")
    current_time_tool_manager = None
    _CURRENT_TIME_AVAILABLE = False

try:
    from tools.service.mcpCalling import mcp_calling_tool_manager

    _MCP_CALLING_AVAILABLE = True
except ImportError as e:
    print(f"⚠️ mcpCalling工具导入失败: {e}")
    mcp_calling_tool_manager = None
    _MCP_CALLING_AVAILABLE = False

try:
    from tools.service.GetMemoryHis import memory_history_tool_manager

    _MEMORY_HIS_AVAILABLE = True
except ImportError as e:
    print(f"⚠️ GetMemoryHis工具导入失败: {e}")
    memory_history_tool_manager = None
    _MEMORY_HIS_AVAILABLE = False

try:
    from tools.service.WebSearch import web_search_toolkit_manager

    _WEB_SEARCH_AVAILABLE = True
except ImportError as e:
    print(f"⚠️ WebSearch工具导入失败: {e}")
    web_search_toolkit_manager = None
    _WEB_SEARCH_AVAILABLE = False

try:
    from tools.service.browserUseTool import browser_use_tool_manager

    _BROWSER_USE_AVAILABLE = True
except ImportError as e:
    print(f"⚠️ browserUseTool工具导入失败: {e}")
    browser_use_tool_manager = None
    _BROWSER_USE_AVAILABLE = False


class ToolFactory:
    """工具工厂类"""

    # 工具管理器注册表（基于category_code）
    _tool_managers: Dict[str, Any] = {}

    # 工具函数注册表（基于category_code）
    _tool_functions: Dict[str, Any] = {}

    @classmethod
    def register_tool_manager(cls, tool_manager: Any) -> None:
        """注册工具管理器"""
        category_code = tool_manager.category_code
        cls._tool_managers[category_code] = tool_manager

        # 获取LangChain工具，可能是单个工具或工具列表
        langchain_tools = tool_manager.get_langchain_tool()

        # 如果是工具集（返回列表），存储工具列表
        if isinstance(langchain_tools, list):
            cls._tool_functions[category_code] = langchain_tools
        else:
            # 单个工具，保持原有逻辑
            cls._tool_functions[category_code] = langchain_tools

        print(f"工具管理器注册成功: '{category_code}' -> {tool_manager.category_name}")

    @classmethod
    def auto_register_tools(cls) -> None:
        """自动注册所有工具"""
        registered_count = 0

        # 注册当前时间工具
        if _CURRENT_TIME_AVAILABLE and current_time_tool_manager:
            cls.register_tool_manager(current_time_tool_manager)
            registered_count += 1

        # 注册MCP调用工具
        if _MCP_CALLING_AVAILABLE and mcp_calling_tool_manager:
            cls.register_tool_manager(mcp_calling_tool_manager)
            registered_count += 1

        # 注册历史记忆工具
        if _MEMORY_HIS_AVAILABLE and memory_history_tool_manager:
            cls.register_tool_manager(memory_history_tool_manager)
            registered_count += 1

        # 注册Web搜索工具集
        if _WEB_SEARCH_AVAILABLE and web_search_toolkit_manager:
            cls.register_tool_manager(web_search_toolkit_manager)
            registered_count += 1

        # 注册浏览器自动化工具
        if _BROWSER_USE_AVAILABLE and browser_use_tool_manager:
            cls.register_tool_manager(browser_use_tool_manager)
            registered_count += 1

        print(f"✅ 工具自动注册完成，成功注册 {registered_count} 个工具管理器")
        # 后续可以在这里添加更多工具的自动注册

    @classmethod
    def create_tool(cls, category_code: str, **kwargs) -> Optional[Union[BaseTool, List[BaseTool]]]:
        """根据category_code创建工具实例"""
        tool_func = cls._tool_functions.get(category_code)
        if tool_func:
            try:
                # 如果是工具集（列表），直接返回工具列表
                if isinstance(tool_func, list):
                    return tool_func
                else:
                    # 单个工具，返回单个工具实例
                    return tool_func
            except Exception as e:
                print(f"创建工具失败 (代码: {category_code}): {e}")
                return None
        else:
            print(f"未找到工具类型: {category_code}")
            return None

    @classmethod
    def initialize_all_tools(cls, db_session: Session) -> Dict[str, bool]:
        """初始化所有工具到数据库"""
        results: Dict[str, bool] = {}

        try:
            # 自动注册工具（如果还没有注册）
            if not cls._tool_managers:
                cls.auto_register_tools()

            # 初始化每个工具管理器
            for category_code, manager in cls._tool_managers.items():
                try:
                    results[category_code] = manager.initialize(db_session)
                except Exception as e:
                    print(f"初始化工具失败 (代码: {category_code}): {e}")
                    results[category_code] = False

            print("工具工厂初始化完成")

        except Exception as e:
            print(f"工具工厂初始化失败: {e}")
            results["error"] = False

        return results

    @classmethod
    def get_available_types(cls) -> List[str]:
        """获取可用的工具类型（category_code列表）"""
        if not cls._tool_managers:
            cls.auto_register_tools()
        return list(cls._tool_managers.keys())

    @classmethod
    def get_enabled_tools(cls, db_session: Session) -> List[str]:
        """从数据库获取启用的基础工具列表"""
        try:
            from pojo.ai_web_tools_model import AIWebToolsModel
            from pojo.ai_web_detail_tools_model import AIWebDetailToolsModel

            enabled_tools: List[str] = []

            # 查询所有启用的工具集
            enabled_tool_categories = db_session.query(AIWebToolsModel).filter(
                AIWebToolsModel.is_enabled == 1
            ).all()

            for tools_model in enabled_tool_categories:
                if tools_model.category_code in cls._tool_managers:
                    # 检查该工具集下是否有启用的基础工具（tool_type=1）
                    has_enabled_tools = db_session.query(AIWebDetailToolsModel).filter(
                        AIWebDetailToolsModel.parent_id == tools_model.id,
                        AIWebDetailToolsModel.tool_type == 1,
                        AIWebDetailToolsModel.is_enabled == True
                    ).first()

                    if has_enabled_tools:
                        enabled_tools.append(tools_model.category_code)
                        print(f"启用的基础工具集: {tools_model.category_code} - {tools_model.category_name}")

            print(f"总共找到 {len(enabled_tools)} 个启用的基础工具集")
            return enabled_tools

        except Exception as e:
            print(f"获取启用基础工具失败: {e}")
            return []

    @classmethod
    def get_enabled_detail_tools(cls, db_session: Session) -> List[Dict[str, Any]]:
        """从数据库获取启用的基础工具详情列表"""
        try:
            from pojo.ai_web_tools_model import AIWebToolsModel
            from pojo.ai_web_detail_tools_model import AIWebDetailToolsModel

            enabled_detail_tools: List[Dict[str, Any]] = []

            # 查询所有启用的工具集及其启用的基础工具详情（tool_type=1）
            query = db_session.query(
                AIWebToolsModel, AIWebDetailToolsModel
            ).join(
                AIWebDetailToolsModel,
                AIWebToolsModel.id == AIWebDetailToolsModel.parent_id
            ).filter(
                AIWebToolsModel.is_enabled == 1,
                AIWebDetailToolsModel.tool_type == 1,
                AIWebDetailToolsModel.is_enabled == True
            )

            for tools_model, detail_tool in query.all():
                if tools_model.category_code in cls._tool_managers:
                    tool_info = detail_tool.to_dict()
                    tool_info['category_code'] = tools_model.category_code
                    tool_info['category_name'] = tools_model.category_name
                    enabled_detail_tools.append(tool_info)

            print(f"找到 {len(enabled_detail_tools)} 个启用的基础工具详情")
            return enabled_detail_tools

        except Exception as e:
            print(f"获取启用基础工具详情失败: {e}")
            return []

    @classmethod
    def create_enabled_tools(cls, db_session: Session) -> List[BaseTool]:
        """创建所有启用的工具实例"""
        enabled_tool_codes = cls.get_enabled_tools(db_session)
        tools: List[BaseTool] = []

        for category_code in enabled_tool_codes:
            tool_result = cls.create_tool(category_code)
            if tool_result:
                # 如果是工具集（列表），添加所有工具
                if isinstance(tool_result, list):
                    tools.extend(tool_result)
                else:
                    # 单个工具，直接添加
                    tools.append(tool_result)

        return tools

    @classmethod
    def create_enabled_tools_by_detail(cls, db_session: Session) -> List[BaseTool]:
        """根据具体的工具详情创建启用的工具实例（更精确的控制）"""
        enabled_detail_tools = cls.get_enabled_detail_tools(db_session)
        tools: List[BaseTool] = []

        # 按category_code分组
        tools_by_category: Dict[str, List[Dict[str, Any]]] = {}
        for detail_tool in enabled_detail_tools:
            category_code = detail_tool['category_code']
            if category_code not in tools_by_category:
                tools_by_category[category_code] = []
            tools_by_category[category_code].append(detail_tool)

        # 为每个category创建工具实例
        for category_code, detail_tools_list in tools_by_category.items():
            tool_result = cls.create_tool(category_code)
            if tool_result:
                # 如果是工具集（列表），需要根据启用状态过滤
                if isinstance(tool_result, list):
                    # 获取启用的工具名称列表
                    enabled_tool_names = {tool['tool_name'] for tool in detail_tools_list}
                    # 过滤工具（这里需要工具有name属性）
                    filtered_tools = [
                        tool for tool in tool_result
                        if hasattr(tool, 'name') and tool.name in enabled_tool_names
                    ]
                    tools.extend(filtered_tools)
                else:
                    # 单个工具，检查是否在启用列表中
                    if hasattr(tool_result, 'name'):
                        enabled_tool_names = {tool['tool_name'] for tool in detail_tools_list}
                        if tool_result.name in enabled_tool_names:
                            tools.append(tool_result)
                    else:
                        # 如果工具没有name属性，默认添加
                        tools.append(tool_result)

        return tools

    @classmethod
    def get_tool_manager(cls, category_code: str):
        """根据category_code获取工具管理器"""
        return cls._tool_managers.get(category_code)

    @classmethod
    def get_registered_managers(cls) -> Dict[str, Any]:
        """获取所有已注册的工具管理器"""
        if not cls._tool_managers:
            cls.auto_register_tools()
        return cls._tool_managers.copy()

    @classmethod
    def create_tools_from_list(cls, tools_list: List[Union[str, Dict[str, Any]]]) -> List[BaseTool]:
        """从工具列表创建工具实例"""
        tools: List[BaseTool] = []

        if not tools_list:
            return tools

        # 自动注册工具（如果还没有注册）
        if not cls._tool_managers:
            cls.auto_register_tools()

        # 处理不同的工具列表格式
        for tool_config in tools_list:
            try:
                # 如果是字符串，则假设是category_code
                if isinstance(tool_config, str):
                    category_code = tool_config
                    tool_result = cls.create_tool(category_code)
                    if tool_result:
                        # 如果是工具集（列表），添加所有工具
                        if isinstance(tool_result, list):
                            tools.extend(tool_result)
                        else:
                            # 单个工具，直接添加
                            tools.append(tool_result)
                    else:
                        print(f"工具配置缺少category_code或type字段: {tool_config}")

            except Exception as e:
                print(f"创建工具失败: {tool_config}, 错误: {e}")
                continue

        print(f"成功创建了 {len(tools)} 个工具")
        return tools

    @classmethod
    def create_single_tool(cls, category_code: str, tool_name: str = None) -> Optional[BaseTool]:
        """根据category_code和tool_name创建单个工具实例
        
        Args:
            category_code: 工具类别代码，对应注册的工具管理器
            tool_name: 可选，具体的工具名称。如果不提供，则返回该类别下的第一个工具
                
        Returns:
            BaseTool实例或None
        """
        try:
            # 自动注册工具（如果还没有注册）
            if not cls._tool_managers:
                cls.auto_register_tools()

            # 检查category_code是否存在
            if category_code not in cls._tool_managers:
                print(f"⚠️ 未找到工具类别: {category_code}")
                return None

            # 根据category_code创建工具
            tool_result = cls.create_tool(category_code)
            
            if not tool_result:
                print(f"⚠️ 工具类别 {category_code} 创建失败")
                return None

            # 如果是工具集（返回列表）
            if isinstance(tool_result, list):

                # 在工具集中查找指定名称的工具
                for tool in tool_result:
                    if hasattr(tool, 'name') and tool.name == tool_name:
                        return tool
                print(f"⚠️ 在工具集 {category_code} 中未找到工具: {tool_name}")
                # 列出可用的工具名称
                available_tools = [tool.name for tool in tool_result if hasattr(tool, 'name')]
                print(f"   可用工具: {available_tools}")
                return None
            else:
                # 检查工具名称是否匹配
                if hasattr(tool_result, 'name') and tool_result.name == tool_name:
                    print(f"✅ 找到匹配工具: {category_code}.{tool_name}")
                    return tool_result
                else:
                    actual_name = getattr(tool_result, 'name', 'unknown')
                    print(f"⚠️ 工具名称不匹配: 期望 {tool_name}, 实际 {actual_name}")
                    return None

        except Exception as e:
            print(f"❌ 创建单个工具失败: category_code={category_code}, tool_name={tool_name}, 错误: {e}")
            return None

    @classmethod
    def _apply_tool_config(cls, tool: BaseTool, config: Dict[str, Any]) -> None:
        """应用工具配置到工具实例
        
        Args:
            tool: BaseTool实例
            config: 配置信息
        """
        try:
            # 应用描述
            if 'description' in config and config['description']:
                if hasattr(tool, 'description'):
                    tool.description = config['description']

            # 应用其他配置参数（如需要可以扩展）
            if 'params_info' in config:
                # 如果工具支持参数信息设置
                if hasattr(tool, 'set_params_info'):
                    tool.set_params_info(config['params_info'])

            # 可以根据需要添加更多配置应用逻辑

        except Exception as e:
            print(f"⚠️ 应用工具配置失败: {e}")

    @classmethod
    def sync_tool_status_from_database(cls, db_session: Session, category_code: str) -> bool:
        """从数据库同步工具状态"""
        try:
            from pojo.ai_web_tools_model import AIWebToolsModel
            from pojo.ai_web_detail_tools_model import AIWebDetailToolsModel

            # 查找工具集
            tools_model = db_session.query(AIWebToolsModel).filter(
                AIWebToolsModel.category_code == category_code
            ).first()

            if not tools_model:
                print(f"未找到工具集: {category_code}")
                return False

            # 查找工具详情
            detail_tools = db_session.query(AIWebDetailToolsModel).filter(
                AIWebDetailToolsModel.parent_id == tools_model.id
            ).all()

            print(f"工具集 '{tools_model.category_name}' 状态: {'启用' if tools_model.is_enabled else '禁用'}")
            print(f"包含 {len(detail_tools)} 个工具:")
            for tool in detail_tools:
                status = '启用' if tool.is_enabled else '禁用'
                print(f"  - {tool.tool_name}: {status}")

            return True

        except Exception as e:
            print(f"同步工具状态失败: {e}")
            return False

    @classmethod
    def get_available_tool_types(cls) -> Dict[str, str]:
        """获取可用的基础工具类型"""
        if not cls._tool_managers:
            cls.auto_register_tools()

        available_types = {}
        for category_code, manager in cls._tool_managers.items():
            available_types[category_code] = manager.category_name

        return available_types

    @classmethod
    def get_tool_details_by_category(cls, db_session: Session, category_code: str) -> List[Dict[str, Any]]:
        """获取指定工具集的详情工具列表"""
        try:
            from pojo.ai_web_tools_model import AIWebToolsModel
            from pojo.ai_web_detail_tools_model import AIWebDetailToolsModel

            # 查找工具集
            tools_model = db_session.query(AIWebToolsModel).filter(
                AIWebToolsModel.category_code == category_code
            ).first()

            if not tools_model:
                print(f"未找到工具集: {category_code}")
                return []

            # 查找基础工具详情（tool_type=1）
            detail_tools = db_session.query(AIWebDetailToolsModel).filter(
                AIWebDetailToolsModel.parent_id == tools_model.id,
                AIWebDetailToolsModel.tool_type == 1
            ).all()

            return [tool.to_dict() for tool in detail_tools]

        except Exception as e:
            print(f"获取工具详情失败: {e}")
            return []

    @classmethod
    def validate_tool_configuration(cls, category_code: str) -> bool:
        """验证工具配置是否正确"""
        try:
            if category_code not in cls._tool_managers:
                print(f"工具类型 {category_code} 未注册")
                return False

            manager = cls._tool_managers[category_code]

            # 检查必要的属性
            if not hasattr(manager, 'category_name') or not manager.category_name:
                print(f"工具管理器 {category_code} 缺少 category_name")
                return False

            if not hasattr(manager, 'category_description') or not manager.category_description:
                print(f"工具管理器 {category_code} 缺少 category_description")
                return False

            # 尝试获取工具配置
            try:
                configs = manager.get_tool_configs()
                if not isinstance(configs, list):
                    print(f"工具管理器 {category_code} 的 get_tool_configs() 必须返回列表")
                    return False
            except Exception as e:
                print(f"工具管理器 {category_code} 的 get_tool_configs() 调用失败: {e}")
                return False

            # 尝试获取 LangChain 工具
            try:
                tool = manager.get_langchain_tool()
                if tool is None:
                    print(f"工具管理器 {category_code} 的 get_langchain_tool() 返回 None")
                    return False
            except Exception as e:
                print(f"工具管理器 {category_code} 的 get_langchain_tool() 调用失败: {e}")
                return False

            print(f"工具配置验证通过: {category_code}")
            return True

        except Exception as e:
            print(f"验证工具配置失败: {e}")
            return False


# 自动注册工具
ToolFactory.auto_register_tools()
